<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name="description" content="多引擎搜索工具，支持Google、Baidu、Bing等多种搜索引擎。请关注微信公众号：《某鸟碎碎》获得更多有趣的技术内容。">
    <title>多引擎搜索工具 - By 某鸟碎碎</title>
    <link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>🔍</text></svg>">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css" integrity="sha512-Fo3rlrZj/k7ujTnHg4CGR2D7kSs0v4LLanw2qksYuRlEzO+tcaEPQogQ0KaoGN26/zrn20ImR1DfuLWnOo7aBA==" crossorigin="anonymous" referrerpolicy="no-referrer" />
    <style>
        :root {
            --primary-color: #4285f4;
            --text-color: #202124;
            --secondary-text: #5f6368;
            --border-color: #dfe1e5;
            --bg-color: #ffffff;
            --card-hover: #f8f9fa;
            --advanced-bg: #f5f7fa;
            --error-color: #d93025;
            --error-bg: #fce8e6;
            --success-color: #0d652d;
        }

        body {
            font-family: 'Segoe UI', Roboto, Arial, sans-serif;
            color: var(--text-color);
            background-color: var(--bg-color);
            margin: 0;
            padding: 0;
            line-height: 1.6;
        }

        .sr-only {
            position: absolute;
            width: 1px;
            height: 1px;
            padding: 0;
            margin: -1px;
            overflow: hidden;
            clip: rect(0, 0, 0, 0);
            white-space: nowrap;
            border-width: 0;
        }

        .container {
            max-width: 800px;
            margin: 0 auto;
            padding: 20px;
        }

        header {
            text-align: center;
            margin-bottom: 30px;
            padding-bottom: 20px;
            border-bottom: 1px solid var(--border-color);
        }

        h1 {
            color: var(--primary-color);
            margin-bottom: 10px;
            font-weight: 500;
        }

        .search-toggle {
            display: flex;
            justify-content: flex-start;
            margin-bottom: 15px;
        }

        .search-form-container {
            background-color: var(--advanced-bg);
            border-radius: 8px;
            padding: 15px;
            margin-bottom: 20px;
            transition: all 0.3s ease;
        }

        .collapsed .search-form {
            display: none;
        }

        .search-form {
            display: flex;
            flex-direction: column;
            gap: 15px;
        }

        .form-group {
            display: flex;
            flex-direction: column;
        }

        label {
            margin-bottom: 8px;
            font-size: 14px;
            color: var(--secondary-text);
        }

        input[type="text"], select, input[type="number"], input[type="password"] {
            padding: 12px 15px;
            border: 1px solid var(--border-color);
            border-radius: 24px;
            font-size: 16px;
            transition: box-shadow 0.3s;
            background-color: white;
        }

        input[type="text"]:focus, select:focus, input[type="number"]:focus, input[type="password"]:focus {
            outline: none;
            box-shadow: 0 1px 6px rgba(32, 33, 36, 0.1);
            border-color: var(--primary-color);
        }

        button {
            background-color: var(--primary-color);
            color: white;
            border: none;
            padding: 12px 24px;
            border-radius: 24px;
            cursor: pointer;
            font-size: 16px;
            font-weight: 500;
            transition: background-color 0.3s;
            align-self: center;
            width: 200px;
        }

        button:hover {
            background-color: #3367d6;
        }

        .toggle-button {
            display: flex;
            align-items: center;
            color: var(--primary-color);
            cursor: pointer;
            font-size: 14px;
            user-select: none;
            background: none;
            border: none;
            padding: 0;
        }

        .toggle-button::before {
            content: "▶";
            margin-right: 8px;
            font-size: 10px;
            transition: transform 0.2s;
        }

        .toggle-button.active::before {
            transform: rotate(90deg);
        }

        .results-container {
            margin-top: 30px;
        }

        .result-count {
            color: var(--secondary-text);
            font-size: 14px;
            margin-bottom: 20px;
        }

        .result-item {
            margin-bottom: 25px;
            padding: 15px;
            border-radius: 8px;
            transition: background-color 0.2s;
        }

        .result-item:hover {
            background-color: var(--card-hover);
        }

        .result-title {
            color: var(--primary-color);
            font-size: 20px;
            font-weight: 400;
            margin-bottom: 5px;
            text-decoration: none;
            display: inline-block;
        }

        .result-title:hover {
            text-decoration: underline;
        }

        .result-url {
            display: flex;
            align-items: center;
            margin-bottom: 5px;
        }

        .result-link {
            color: var(--success-color);
            font-size: 14px;
            text-decoration: none;
        }

        .result-favicon {
            width: 16px;
            height: 16px;
            margin-right: 8px;
            border-radius: 50%;
        }

        .result-snippet {
            color: var(--text-color);
            font-size: 14px;
            margin-bottom: 5px;
        }

        .result-date {
            color: var(--secondary-text);
            font-size: 12px;
        }

        .loading {
            display: none;
            text-align: center;
            margin: 30px 0;
        }

        .spinner {
            border: 4px solid rgba(0, 0, 0, 0.1);
            border-radius: 50%;
            border-top: 4px solid var(--primary-color);
            width: 40px;
            height: 40px;
            animation: spin 1s linear infinite;
            margin: 0 auto;
        }

        @keyframes spin {
            0% { transform: rotate(0deg); }
            100% { transform: rotate(360deg); }
        }

        .error-message {
            color: var(--error-color);
            background-color: var(--error-bg);
            padding: 15px;
            border-radius: 4px;
            margin: 20px 0;
            display: none;
        }

        .engine-info {
            font-size: 12px;
            color: var(--secondary-text);
            margin-top: 5px;
            padding-left: 5px;
        }

        .advanced-params {
            display: none;
            background-color: var(--advanced-bg);
            padding: 15px;
            border-radius: 8px;
            margin-bottom: 15px;
        }

        .param-group {
            margin-bottom: 15px;
        }

        .param-description {
            font-size: 12px;
            color: var(--secondary-text);
            margin-top: 5px;
            margin-bottom: 10px;
            line-height: 1.4;
        }

        .param-row {
            display: flex;
            gap: 10px;
        }

        .param-row select {
            flex: 1;
        }

        .param-row input {
            flex: 2;
        }

        .password-container {
            position: relative;
        }

        .password-toggle {
            position: absolute;
            right: 15px;
            top: 50%;
            transform: translateY(-50%);
            cursor: pointer;
            color: var(--secondary-text);
            background: none;
            border: none;
        }

        .proxy-info {
            font-size: 12px;
            color: var(--secondary-text);
            margin-top: 5px;
            padding-left: 5px;
        }

        @media (max-width: 600px) {
            .container {
                padding: 15px;
            }
            
            input[type="text"], select, input[type="number"], input[type="password"] {
                padding: 10px 15px;
            }
            
            button {
                width: 100%;
            }

            .param-row {
                flex-direction: column;
            }
        }
    </style>
</head>
<body>
    <div class="container">
        <header>
            <h1>多引擎搜索工具 - By 某鸟碎碎</h1>
            <p>选择不同的搜索平台和搜索引擎获取结果</p>
        </header>

        <div class="search-toggle">
            <button type="button" class="toggle-button active" id="searchToggle" aria-expanded="true" aria-controls="searchFormContainer">搜索条件 ▼</button>
        </div>

        <div class="search-form-container" id="searchFormContainer">
            <form id="searchForm" class="search-form" aria-label="搜索表单">
                <div class="form-group">
                    <label for="apiPlatform">选择搜索平台</label>
                    <select id="apiPlatform" required aria-required="true">
                        <option value="">-- 请选择搜索平台 --</option>
                        <option value="searchapi">SearchAPI</option>
                        <option value="serpapi">SerpAPI</option>
                    </select>
                    <div class="engine-info" id="platformInfo"></div>
                </div>

                <div id="proxyContainer" style="display: none;">
                    <div class="form-group">
                        <label for="proxyUrl">CORS代理地址</label>
                        <input type="text" id="proxyUrl" placeholder="例如: https://cors-anywhere.herokuapp.com">
                        <div class="proxy-info">
                            需要CORS代理才能访问此API。您可以自行搭建或使用公共代理服务。
                        </div>
                    </div>
                </div>

                <div class="form-group">
                    <label for="searchEngine">选择搜索引擎</label>
                    <select id="searchEngine" required aria-required="true">
                        <option value="">-- 请选择搜索引擎 --</option>
                        <option value="google">Google</option>
                        <option value="google_news">Google News</option>
                        <option value="baidu">Baidu</option>
                        <option value="bing">Bing</option>
                    </select>
                    <div class="engine-info" id="engineInfo"></div>
                </div>

                <div class="form-group">
                    <label for="keyword">搜索关键词</label>
                    <input type="text" id="keyword" placeholder="输入搜索关键词" required aria-required="true">
                </div>

                <div class="form-group">
                    <label for="num">返回结果数量 (1-100)</label>
                    <input type="number" id="num" placeholder="默认10条" min="1" max="100" value="10">
                </div>

                <div class="form-group">
                    <label for="timePeriod">时间范围</label>
                    <select id="timePeriod">
                        <option value="">-- 选择时间范围 --</option>
                        <option value="last_hour">过去一小时</option>
                        <option value="last_day">过去24小时</option>
                        <option value="last_week">过去一周</option>
                        <option value="last_month">过去一个月</option>
                        <option value="last_year">过去一年</option>
                    </select>
                </div>

                <div class="form-group">
                    <label for="apiKey">API密钥</label>
                    <div class="password-container">
                        <input type="password" id="apiKey" placeholder="输入API密钥" required aria-required="true">
                        <button type="button" class="password-toggle" id="togglePassword" aria-label="显示密码">
                            <i class="fas fa-eye"></i>
                        </button>
                    </div>
                </div>

                <button type="button" class="toggle-button" id="advancedToggle" aria-expanded="false" aria-controls="advancedParams">高级搜索参数 ▼</button>
                
                <div class="advanced-params" id="advancedParams" aria-hidden="true">
                    <div class="param-group">
                        <label for="gl">地区代码 (gl)</label>
                        <div class="param-row">
                            <select id="gl-preset">
                                <option value="">-- 选择预设 --</option>
                                <option value="cn">China</option>
                                <option value="hk">Hong Kong</option>
                                <option value="us">United States</option>
                                <option value="jp">Japan</option>
                                <option value="sg">Singapore</option>
                                <option value="uk">United Kingdom</option>
                            </select>
                            <input type="text" id="gl" placeholder="或自定义地区代码">
                        </div>
                        <div class="param-description">
                            默认参数us定义了搜索的国家/地区。此参数会覆盖cr参数。
                        </div>
                    </div>

                    <div class="param-group">
                        <label for="hl">界面语言 (hl)</label>
                        <div class="param-row">
                            <select id="hl-preset">
                                <option value="">-- 选择预设 --</option>
                                <option value="zh-cn">Chinese (Simplified)</option>
                                <option value="en">English</option>
                                <option value="ja">Japanese</option>
                            </select>
                            <input type="text" id="hl" placeholder="或自定义语言代码">
                        </div>
                        <div class="param-description">
                            默认参数en定义了搜索界面的语言。
                        </div>
                    </div>

                    <div class="param-group">
                        <label for="lr">语言限制 (lr)</label>
                        <input type="text" id="lr" placeholder="例如: lang_jp 或 lang_it|lang_de">
                        <div class="param-description">
                            lr参数将搜索结果限制为用特定语言或一组语言编写的文档。格式为lang_{2字母国家代码}。例如: lang_jp表示日语文档，lang_it|lang_de表示意大利语或德语文档。
                        </div>
                    </div>

                    <div class="param-group">
                        <label for="cr">国家限制 (cr)</label>
                        <div class="param-row">
                            <select id="cr-preset">
                                <option value="">-- 选择预设 --</option>
                                <option value="us">United States</option>
                                <option value="hk">Hong Kong</option>
                                <option value="ca">Canada</option>
                                <option value="de">Germany</option>
                                <option value="es">Spain</option>
                                <option value="fr">France</option>
                                <option value="in">India</option>
                                <option value="jp">Japan</option>
                                <option value="sg">Singapore</option>
                            </select>
                            <input type="text" id="cr" placeholder="或自定义国家代码">
                        </div>
                        <div class="param-description">
                            cr参数将搜索结果限制为源自特定国家的文档。Google根据文档URL的顶级域名(TLD)或Web服务器的IP地址地理位置确定文档的国家。
                        </div>
                    </div>
                </div>

                <button type="submit">搜索</button>
            </form>
        </div>

        <div class="error-message" id="errorMessage" role="alert" aria-live="assertive"></div>

        <div class="loading" id="loading" aria-live="polite" aria-busy="true">
            <div class="spinner" aria-hidden="true"></div>
            <p>正在获取搜索结果...</p>
        </div>

        <section class="results-container" id="resultsContainer">
            <div class="result-count" id="resultCount"></div>
            <div id="resultsList" role="list"></div>
        </section>
    </div>

    <script>
        // 搜索平台信息
        const apiPlatforms = {
            searchapi: {
                name: "SearchAPI",
                url: "https://www.searchapi.io/api/v1/search",
                info: "SearchAPI 提供高质量的搜索引擎结果",
                needsProxy: false
            },
            serpapi: {
                name: "SerpAPI",
                url: "https://serpapi.com/search",
                info: "SerpAPI 是 Google 搜索结果的可靠来源",
                needsProxy: true
            }
        };

        // 搜索引擎信息
        const searchEngines = {
            google: {
                name: "Google",
                info: "全球最流行的搜索引擎"
            },
            google_news: {
                name: "Google News",
                info: "Google新闻搜索"
            },
            baidu: {
                name: "Baidu",
                info: "中国最流行的搜索引擎"
            },
            bing: {
                name: "Bing",
                info: "微软提供的搜索引擎"
            }
        };

        // DOM加载完成后执行
        document.addEventListener('DOMContentLoaded', function() {
            // 监听密码显示/隐藏
            document.getElementById('togglePassword').addEventListener('click', function() {
                const passwordInput = document.getElementById('apiKey');
                const type = passwordInput.getAttribute('type') === 'password' ? 'text' : 'password';
                passwordInput.setAttribute('type', type);
                const icon = this.querySelector('i');
                icon.classList.toggle('fa-eye-slash');
                
                // 更新ARIA标签
                const label = type === 'password' ? '显示密码' : '隐藏密码';
                this.setAttribute('aria-label', label);
            });

            // 监听高级参数切换
            document.getElementById('advancedToggle').addEventListener('click', function() {
                const isExpanded = this.getAttribute('aria-expanded') === 'true';
                this.setAttribute('aria-expanded', !isExpanded);
                this.classList.toggle('active');
                
                const params = document.getElementById('advancedParams');
                params.style.display = params.style.display === 'block' ? 'none' : 'block';
                params.setAttribute('aria-hidden', isExpanded);
            });

            // 监听搜索条件折叠/展开
            document.getElementById('searchToggle').addEventListener('click', function() {
                const isExpanded = this.getAttribute('aria-expanded') === 'true';
                this.setAttribute('aria-expanded', !isExpanded);
                
                const container = document.querySelector('.search-form-container');
                container.classList.toggle('collapsed');
                this.classList.toggle('active');
                
                // 更新箭头方向
                const icon = this.innerHTML.includes('▼') ? '▲' : '▼';
                this.innerHTML = this.innerHTML.replace(/[▼▲]/, icon);
            });

            // 监听搜索平台变化，显示/隐藏代理URL输入
            document.getElementById('apiPlatform').addEventListener('change', function() {
                const selectedPlatform = this.value;
                const proxyContainer = document.getElementById('proxyContainer');
                const platformInfo = document.getElementById('platformInfo');
                
                if (selectedPlatform && apiPlatforms[selectedPlatform]) {
                    platformInfo.textContent = apiPlatforms[selectedPlatform].info;
                    proxyContainer.style.display = apiPlatforms[selectedPlatform].needsProxy ? 'block' : 'none';
                } else {
                    platformInfo.textContent = '';
                    proxyContainer.style.display = 'none';
                }
            });

            // 监听预设选择变化
            document.getElementById('gl-preset').addEventListener('change', function() {
                if (this.value) {
                    document.getElementById('gl').value = this.value;
                }
            });

            document.getElementById('hl-preset').addEventListener('change', function() {
                if (this.value) {
                    document.getElementById('hl').value = this.value;
                }
            });

            document.getElementById('cr-preset').addEventListener('change', function() {
                if (this.value) {
                    document.getElementById('cr').value = this.value;
                }
            });

            // 监听搜索引擎选择变化
            document.getElementById('searchEngine').addEventListener('change', function() {
                const selectedEngine = this.value;
                const engineInfo = document.getElementById('engineInfo');
                
                if (selectedEngine && searchEngines[selectedEngine]) {
                    engineInfo.textContent = searchEngines[selectedEngine].info;
                } else {
                    engineInfo.textContent = '';
                }
            });

            // 表单提交处理
            document.getElementById('searchForm').addEventListener('submit', async function(e) {
                e.preventDefault();
                
                // 获取表单值
                const apiPlatform = document.getElementById('apiPlatform').value;
                const searchEngine = document.getElementById('searchEngine').value;
                const keyword = document.getElementById('keyword').value.trim();
                const num = document.getElementById('num').value || 10;
                const timePeriod = document.getElementById('timePeriod').value;
                const apiKey = document.getElementById('apiKey').value.trim();
                const proxyUrl = document.getElementById('proxyUrl').value.trim();
                
                // 获取高级参数
                const gl = document.getElementById('gl').value.trim();
                const hl = document.getElementById('hl').value.trim();
                const lr = document.getElementById('lr').value.trim();
                const cr = document.getElementById('cr').value.trim();
                
                // 验证表单
                if (!apiPlatform) {
                    showError('请选择搜索平台');
                    document.getElementById('apiPlatform').focus();
                    return;
                }
                
                if (!searchEngine) {
                    showError('请选择搜索引擎');
                    document.getElementById('searchEngine').focus();
                    return;
                }
                
                if (!keyword) {
                    showError('请输入搜索关键词');
                    document.getElementById('keyword').focus();
                    return;
                }
                
                if (!apiKey) {
                    showError('请输入API密钥');
                    document.getElementById('apiKey').focus();
                    return;
                }
                
                if (apiPlatforms[apiPlatform].needsProxy && !proxyUrl) {
                    showError('请提供CORS代理地址');
                    document.getElementById('proxyUrl').focus();
                    return;
                }
                
                // 显示加载状态
                document.getElementById('loading').style.display = 'block';
                document.getElementById('errorMessage').style.display = 'none';
                document.getElementById('resultsList').innerHTML = '';
                document.getElementById('resultCount').textContent = '';
                
                try {
                    // 构建API URL
                    const platformConfig = apiPlatforms[apiPlatform];
                    const engineConfig = searchEngines[searchEngine];
                    
                    let apiUrl = `${platformConfig.url}?engine=${encodeURIComponent(searchEngine)}&q=${encodeURIComponent(keyword)}`;
                    
                    // 添加结果数量参数
                    apiUrl += `&num=${encodeURIComponent(num)}`;
                    
                    // 添加时间范围参数
                    if (timePeriod) apiUrl += `&time_period=${encodeURIComponent(timePeriod)}`;
                    
                    // 添加高级参数
                    if (gl) apiUrl += `&gl=${encodeURIComponent(gl)}`;
                    if (hl) apiUrl += `&hl=${encodeURIComponent(hl)}`;
                    if (lr) apiUrl += `&lr=${encodeURIComponent(lr)}`;
                    if (cr) apiUrl += `&cr=${encodeURIComponent(cr)}`;
                    
                    apiUrl += `&api_key=${encodeURIComponent(apiKey)}`;
                    
                    // 处理需要代理的平台
                    let fetchOptions = {};
                    if (platformConfig.needsProxy) {
                        // 使用用户提供的代理
                        apiUrl = `${proxyUrl}/${apiUrl}`;
                        fetchOptions = {
                            headers: {
                                'X-Requested-With': 'XMLHttpRequest'
                            }
                        };
                    }
                    
                    // 发起请求
                    const response = await fetch(apiUrl, fetchOptions);
                    
                    if (!response.ok) {
                        const errorData = await response.json().catch(() => ({}));
                        throw new Error(errorData.error || `HTTP错误! 状态码: ${response.status}`);
                    }
                    
                    const data = await response.json();
                    
                    document.getElementById('loading').style.display = 'none';
                    
                    if (data.organic_results && data.organic_results.length > 0) {
                        displayResults(data.organic_results, platformConfig.name, engineConfig.name);
                        // 搜索成功后折叠搜索区域
                        document.querySelector('.search-form-container').classList.add('collapsed');
                        document.getElementById('searchToggle').classList.add('active');
                        document.getElementById('searchToggle').innerHTML = '搜索条件 ▲';
                        document.getElementById('searchToggle').setAttribute('aria-expanded', 'false');
                    } else {
                        document.getElementById('resultCount').textContent = '没有找到相关结果';
                        document.getElementById('resultCount').setAttribute('aria-live', 'polite');
                    }
                } catch (error) {
                    document.getElementById('loading').style.display = 'none';
                    showError(`发生错误: ${error.message}`);
                    console.error('Error:', error);
                }
            });
        });

        function showError(message) {
            const errorMessage = document.getElementById('errorMessage');
            errorMessage.textContent = message;
            errorMessage.style.display = 'block';
            // 确保屏幕阅读器能读到错误信息
            errorMessage.setAttribute('aria-live', 'assertive');
        }

        function displayResults(results, platformName, engineName) {
            const resultsList = document.getElementById('resultsList');
            const resultCount = document.getElementById('resultCount');
            
            resultCount.textContent = `使用 ${platformName} 的 ${engineName} 找到约 ${results.length} 条结果`;
            resultCount.setAttribute('aria-live', 'polite');
            
            resultsList.innerHTML = '';
            
            results.forEach(result => {
                const resultItem = document.createElement('article');
                resultItem.className = 'result-item';
                resultItem.setAttribute('role', 'listitem');
                
                const titleLink = document.createElement('a');
                titleLink.className = 'result-title';
                titleLink.href = result.link;
                titleLink.textContent = result.title || '无标题';
                titleLink.target = '_blank';
                titleLink.rel = 'noopener noreferrer';
                
                const urlContainer = document.createElement('div');
                urlContainer.className = 'result-url';
                
                if (result.favicon) {
                    const favicon = document.createElement('img');
                    favicon.className = 'result-favicon';
                    favicon.src = result.favicon;
                    favicon.alt = '';
                    urlContainer.appendChild(favicon);
                }
                
                const urlLink = document.createElement('a');
                urlLink.className = 'result-link';
                urlLink.href = result.link;
                urlLink.textContent = result.displayed_link || result.link || '无链接';
                urlLink.target = '_blank';
                urlLink.rel = 'noopener noreferrer';
                urlContainer.appendChild(urlLink);
                
                const snippet = document.createElement('div');
                snippet.className = 'result-snippet';
                snippet.textContent = result.snippet || '无描述';
                
                resultItem.appendChild(titleLink);
                resultItem.appendChild(urlContainer);
                resultItem.appendChild(snippet);
                
                if (result.date) {
                    const date = document.createElement('div');
                    date.className = 'result-date';
                    date.textContent = result.date;
                    resultItem.appendChild(date);
                }
                
                resultsList.appendChild(resultItem);
            });
        }
    </script>
</body>
</html>